//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.1.1
#include "gpio_bsp.h"

/*GPIO端口时钟*/
static void WHT_GPIO_BSP_Set_Clock(WHT_GPIO_Port_enum portx, FunctionalState state)
{
    unsigned int RCC_APB2Periph;

    switch (portx)
    {
    case PortA:RCC_APB2Periph = RCC_APB2Periph_GPIOA; break;
    case PortB:RCC_APB2Periph = RCC_APB2Periph_GPIOB; break;
    case PortC:RCC_APB2Periph = RCC_APB2Periph_GPIOC; break;
    case PortD:RCC_APB2Periph = RCC_APB2Periph_GPIOD; break;
    case PortE:RCC_APB2Periph = RCC_APB2Periph_GPIOE; break;
    case PortF:RCC_APB2Periph = RCC_APB2Periph_GPIOF; break;
    case PortG:RCC_APB2Periph = RCC_APB2Periph_GPIOG; break;
    default:
        return;
    }
    RCC_APB2PeriphClockCmd(RCC_APB2Periph, state);
}

/*GPIO引脚工作模式*/
static void WHT_GPIO_BSP_Set_Mode(WHT_GPIO_Port_enum portx, uint16_t pinx, WHT_GPIO_Mode_enum mode)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode = (GPIOMode_TypeDef)mode;
    GPIO_InitStruct.GPIO_Pin = pinx;
    GPIO_Init((GPIO_TypeDef*)portx, &GPIO_InitStruct);
}

/*设置GPIO引脚状态*/
static void WHT_GPIO_BSP_Set_State(WHT_GPIO_Port_enum portx, uint16_t pinx, WHT_GPIO_State_enum state)
{
    GPIO_WriteBit((GPIO_TypeDef*)portx, pinx, (BitAction)state);
}

/*获取GPIO引脚状态*/
static WHT_GPIO_State_enum WHT_GPIO_BSP_Get_State(WHT_GPIO_Port_enum portx, uint16_t pinx)
{
    return (WHT_GPIO_State_enum)GPIO_ReadInputDataBit((GPIO_TypeDef*)portx, pinx);
}

/*获取GPIO端口状态*/
static uint16_t WHT_GPIO_BSP_Get_Prot_Value(WHT_GPIO_Port_enum portx)
{
    return GPIO_ReadInputData((GPIO_TypeDef*)portx);
}

/*设置GPIO端口状态*/
static void WHT_GPIO_BSP_Set_Port_Value(WHT_GPIO_Port_enum portx, uint16_t port_value)
{
    GPIO_Write((GPIO_TypeDef*)portx, port_value);
}

/*注册位带操作读取*/
static void WHT_GPIO_BSP_Config_Bit_Output(WHT_GPIO_Port_enum portx, WHT_GPIO_Pin_enum pinx, volatile unsigned int** output)
{
    unsigned int GPIO_ODR_Address;

    //原理为：#define WHT_Set_GPIO_Pin_State(WHT_GPIO_Port_enum,WHT_GPIO_Pin_Number_enum)    (*((volatile unsigned int*)(((WHT_GPIO_Port_enum+0x0c)&0xf0000000)+0x02000000+(((WHT_GPIO_Port_enum+0x0c)&0x00ffffff)<<5)+(WHT_GPIO_Pin_Number_enum<<2))))
    GPIO_ODR_Address =  ((portx + GPIO_ODR_Offset_Address) & 0xf0000000) + 0x02000000;
    GPIO_ODR_Address += ((portx + GPIO_ODR_Offset_Address) & 0x00ffffff) << 5;
    GPIO_ODR_Address += (32 - __clz(pinx) - 1) << 2;
    *output = (volatile unsigned int*)GPIO_ODR_Address;
}

/*注册未带操作写*/
static void WHT_GPIO_BSP_Config_Bit_Input(WHT_GPIO_Port_enum portx, WHT_GPIO_Pin_enum pinx, volatile unsigned int** input)
{
    unsigned int GPIO_IDR_Address;
    //原理为：#define WHT_Get_GPIO_Pin_State(WHT_GPIO_Port_enum,WHT_GPIO_Pin_Number_enum)    (*((volatile unsigned int*)(((WHT_GPIO_Port_enum+0x08)&0xf0000000)+0x02000000+(((WHT_GPIO_Port_enum+0x08)&0x00ffffff)<<5)+(WHT_GPIO_Pin_Number_enum<<2))))
    GPIO_IDR_Address =  ((portx + GPIO_IDR_Offset_Address) & 0xf0000000) + 0x02000000;
    GPIO_IDR_Address += ((portx + GPIO_IDR_Offset_Address) & 0x00ffffff) << 5;
    GPIO_IDR_Address += (32 - __clz(pinx) - 1) << 2;
    *input = (volatile unsigned int*)GPIO_IDR_Address;
}


/*全局常量*/
const WHT_GPIO_BSP_t WHT_GPIO_BSP =
{
    .WHT_Set_Clock         = WHT_GPIO_BSP_Set_Clock,
    .WHT_Set_Mode          = WHT_GPIO_BSP_Set_Mode,
    .WHT_Get_State         = WHT_GPIO_BSP_Get_State,
    .WHT_Set_State         = WHT_GPIO_BSP_Set_State,
    .WHT_Get_Prot_Value    = WHT_GPIO_BSP_Get_Prot_Value,
    .WHT_Set_Prot_Value    = WHT_GPIO_BSP_Set_Port_Value,
    .WHT_Config_Bit_Output = WHT_GPIO_BSP_Config_Bit_Output,
    .WHT_Config_Bit_Input  = WHT_GPIO_BSP_Config_Bit_Input,
};
